<?php
/**
 *User.php    当前文件名
 *Administrator         当前用户
 *15:46         系统时间
 *yydati 工程名
 *PhpStorm IDE名称
 **/

namespace app\api\controller;


use app\BaseController;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Validate;

class Exam extends BaseController
{
    /**
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 获取考试信息
     */
    public function getExamInfo()
    {
        $userId = $this->request->user_id;
        $examinfo = Db::name('exam')
            ->where('status', 1)
            ->withoutField('status,create_time,mark,update_time')
            ->find();
        if (empty($examinfo)) {
            return message('暂无可参与的考试', false);
        }
        $exam_status = Db::name('exam_log')
            ->where('exam_id', $examinfo['id'])
            ->where('user_id', $userId)
            ->value('status');
        $examinfo['is_exam'] = $exam_status;
        return message("操作成功", true, $examinfo);
    }

    /**
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 获取考试题目
     */
    public function getExamProblem()
    {
        $params = input('post.');
        $userId = $this->request->user_id;
        $exam_info = Db::name('exam')
            ->where('id', $params['id'])
            ->where('mark', 1)
            ->field('id,title,topic_ids,is_rand,start_time,end_time,problem_num,minute')
            ->find();
        if (empty($exam_info)) {
            return message('暂无可参与的考试', false);
        }
        if ($exam_info['end_time'] < date('Y-m-d H:i:s')) {
            $data = [
                'exam_info' => $exam_info,
                'problem' => [],
            ];
            return message('考试已截止', false, $data);
        }
        $exam_log = Db::name('exam_log')
            ->where('exam_id', $exam_info['id'])
            ->where('user_id', $userId)
            ->where('mark', 1)
            ->field('id,problem_ids,id,status')
            ->find();
        if (empty($exam_log)) {
            $topic_ids = $exam_info['topic_ids'];
            $topic_ids = explode(',', $topic_ids);
            $prescriptionInfo = Db::name('prescription')
                ->whereIn('topic_id', $topic_ids)
                ->where('status', 1)
                ->where('num', '>', 0)
                ->where('mark', 1)
                ->field('id,topic_id')
                ->select()
                ->toArray();
            $topicIds = array_unique(array_column($prescriptionInfo, 'topic_id'));
            // 根据 topic_id 分组
            $groupedArray = array_reduce($topicIds, function ($result, $topicId) use ($prescriptionInfo) {
                $result[$topicId] = array_filter($prescriptionInfo, function ($item) use ($topicId) {
                    return $item['topic_id'] === $topicId;
                });
                return $result;
            }, []);
            // 对每个topic_id对应的数组进行随机选择
            // 遍历外层数组
            foreach ($groupedArray as $topicId => $innerArray) {
                // 复制子数组，避免影响原始数据
                $shuffledArray = $innerArray;
                // 如果子数组有多个元素，则随机打乱它
                if (count($shuffledArray) > 1) {
                    shuffle($shuffledArray);
                }
                // 从随机打乱的子数组中选择一个元素
                $randomSelections[$topicId] = reset($shuffledArray);
            }
            $prescriptionIds = array_column($randomSelections, 'id');

            $examp = Db::name('exam_problem')
                ->whereIn('prescription_id', $prescriptionIds)
                ->where('status', 1)
                ->where('mark', 1)
                ->field('id,title,score,prescription_id')
                ->select()
                ->toArray();
            $problemIds = array_column($examp, 'id');
            $data = [
                'exam_id' => $exam_info['id'],
                'user_id' => $userId,
                'type' => 1,
                'mark' => 1,
                'num' => count($problemIds),
                'problem_ids' => implode(',', $problemIds),
                'create_time' => time(),
                'update_time' => time(),
            ];
            $exam_log_id = Db::name('exam_log')->insertGetId($data);
        } else {
            if ($exam_log['status'] == 1) {
                return message('考试已完成', false);
            }
            $problem_ids = explode(',', $exam_log['problem_ids']);
            $examp = Db::name('exam_problem')
                ->whereIn('id', $problem_ids)
                ->where('status', 1)
                ->where('mark', 1)
                ->field('id,title,score,prescription_id')
                ->select()
                ->toArray();
            $exam_log_id = $exam_log['id'];
            $problemIds = array_column($examp, 'id');
        }
//        1 随机 2 固定 出题顺序
        if ($exam_info['is_rand'] == 1) {
            shuffle($examp);
        }
        $prescriptionIds = array_column($examp, 'prescription_id');
        $prescriptionInfo = Db::name('prescription')
            ->whereIn('id', $prescriptionIds)
            ->field('id,title,problem_img')
            ->select()
            ->toArray();
        $answerInfo = Db::name('answer')
            ->whereIn('problem_id', $problemIds)
            ->where('type', 2)
            ->withoutField('create_time,status,update_time,type')
            ->select()
            ->toArray();
        foreach ($examp as &$prob) {
            $prob['ans'] = [];
            $prob['prescription_name'] = '';
            foreach ($answerInfo as $ans) {
                if ($prob['id'] == $ans['problem_id']) {
                    unset($ans['problem_id'], $ans['id']);
                    $prob['ans'][] = $ans;
                }
            }
            foreach ($prescriptionInfo as $prescriptionItem) {
                if ($prob['prescription_id'] == $prescriptionItem['id']) {
                    $prob['prescription_name'] = $prescriptionItem['title'];
                    $prob['problem_img'] = $prescriptionItem['problem_img'];
                }
            }
        }
        $exam_info['exam_log_id'] = $exam_log_id;
        $examp = array_reduce($examp, function ($result, $item) {
            // 获取当前项的年龄值作为分组依据
            $key = $item['prescription_name'];

            if (!isset($result[$key])) {
                // 如果该年龄还没有被分组过，则创建新的分组并将其添加到结果集合中
                $result[$key] = [];
            }
            unset($item['prescription_id']);
            // 将当前项添加到相应的分组中
            $result[$key][] = $item;

            return $result;
        }, []);
        $data = [
            'exam_info' => $exam_info,
            'problem' => $examp,
        ];
        unset($exam_info, $examp, $answerInfo, $prescriptionInfo, $prescriptionIds);
        return message("操作成功", true, $data);
    }

    /**
     * 提交答案
     */
    public function subAnswer()
    {
        $params = input('post.');
        $userId = $this->request->user_id;
        $rule = [
            'problem_id|题目编号' => 'require',
            'exam_id|考试编号' => 'require',
            'exam_log_id|考试记录ID' => 'require',
            'answer|答案' => 'require',
        ];
        $validate = Validate::rule($rule);
        if (!$validate->check($params)) {
            return message($validate->getError(), false);
        }
        if (!empty($captcha)) {
            $captcha = $this->request->post('captcha');
            $captchaKey = $this->request->post('key');
            $cacheCaptcha = Cache::get($captchaKey);
            if (strtoupper($captcha) != $cacheCaptcha) {
                return message("验证码有误", false, []);
            }
        }
        $exam_problem_info = Db::name('exam_problem')
            ->where('id', $params['problem_id'])
            ->field('right_key,score')
            ->find();
        if (empty($exam_problem_info)) {
            return message('该题目不存在', false);
        }
        $scoreInfo = $this->sumScore(strtoupper($params['answer']), $exam_problem_info);
        $isExitsId = Db::name('exam_user_answer')
            ->where('exam_log_id', $params['exam_log_id'])
            ->where('problem_id', $params['problem_id'])
            ->where('user_id', $userId)
            ->where('type', 1)
            ->value('id');
        if (empty($isExitsId)) {
            $data = [
                'exam_log_id' => $params['exam_log_id'],
                'problem_id' => $params['problem_id'],
                'exam_id' => $params['exam_id'],
                'answer' => $params['answer'],
                'user_id' => $userId,
                'type' => 1,
                'status' => $scoreInfo['status'],
                'score' => $scoreInfo['score'],
                'create_time' => date('Y-m-d H:i:s'),
                'update_time' => date('Y-m-d H:i:s'),
            ];
            Db::name('exam_user_answer')->insert($data);
        } else {
//            TODO 分数待算
            $updata = [
                'score' => $scoreInfo['score'],
            ];
            Db::name('exam_user_answer')
                ->where('id', $isExitsId)
                ->update($updata);
        }
        return message('提交成功', true);
    }

    /**
     * @param $answer
     * @param $exam_problem_info
     * @return int
     * 计算该题得分情况
     */
    public function sumScore($answer, $exam_problem_info)
    {
        $right_key = $exam_problem_info['right_key'];
        $right_key_array = str_split($right_key);
        $answer_array = str_split($answer);
        if ($answer == $right_key) {
            $score = $exam_problem_info['score'];
            $data = [
                'score' => $score,
                'status' => 1,
            ];
            return $data;
        }
        foreach ($answer_array as $answeritem) {
            if (!in_array($answeritem, $right_key_array)) {
                $data = [
                    'score' => 0,
                    'status' => 2,
                ];
                return $data;
            } else {
                $data = [
                    'score' => 1,
                    'status' => 3,
                ];
                return $data;
            }
        }
    }

    /**
     * 提交考试成绩
     * 正确的统计一下
     * 错误的统计一下
     * 未作答的题目也记录一下
     */
    public function subExam()
    {
        $params = input('post.');
        $rule = [
            'exam_id|考试编号' => 'require',
            'exam_log_id|考试记录编号' => 'require',
            'usetime|考试用时' => 'require',
        ];
        $validate = Validate::rule($rule);
        if (!$validate->check($params)) {
            return message($validate->getError(), false);
        }
        $allscore = Db::name('exam_user_answer')
            ->where('exam_log_id', $params['exam_log_id'])
            ->where('type', 1)
            ->sum('score');
        $answerIds = Db::name('exam_user_answer')
            ->where('exam_log_id', $params['exam_log_id'])
            ->where('type', 1)
            ->column('problem_id');
        $problemIds = Db::name('exam_log')
            ->where('id', $params['exam_log_id'])
            ->where('type', 1)
            ->value('problem_ids');
        if (empty($problemIds)) {
            return message('提交失败', true);
        }
        $userId = $this->request->user_id;
        $problemIds = explode(',', $problemIds);
        $unanswerProblemIds = array_diff($problemIds, $answerIds);
        if (!empty($unanswerProblemIds)) {
            $saveData = [];
            foreach ($unanswerProblemIds as $problem_id) {
                $saveData[] = [
                    'exam_log_id' => $params['exam_log_id'],
                    'problem_id' => $problem_id,
                    'exam_id' => $params['exam_id'],
                    'answer' => '',
                    'user_id' => $userId,
                    'type' => 1,
                    'status' => 4,
                    'score' => 0,
                    'create_time' => date('Y-m-d H:i:s'),
                    'update_time' => date('Y-m-d H:i:s'),
                ];
            }
            Db::name('exam_user_answer')->insertAll($saveData);
        }
        $data = [
            'score' => $allscore,
            'status' => 1,
            'unanswer_num' => count($unanswerProblemIds),
            'answer_num' => count($answerIds),
            'usetime' => $params['usetime'],
        ];
        Db::name('exam_log')
            ->where('id', $params['exam_log_id'])
            ->update($data);
        return message('提交成功', true);
    }
}